<#--
=======================================================================================================================
 FTL INITIALIZATION
=======================================================================================================================
 -->
<#-- Includes -->
<#include "../auxftl/constants.ftl">
<#include "../auxftl/propertyutils.ftl">
<#include "../auxftl/viewutils.ftl">
<#-- Global lists -->
<#assign propertyList = createPropertyList()/>
<#assign relationList = createRelationList()/>

<#--
=======================================================================================================================
 PACKAGE AND IMPORTS
=======================================================================================================================
 -->
<#-- Package -->
package ${controllerPackage};

<#if pojo.packageName != "">
import ${pojo.packageName}.*;
</#if>

import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.DefaultHandler;

import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;

import org.hibernate.Session;
import org.hibernate.Transaction;
<#-- Test whether entity contains unique properties, if so, add some imports  -->
<#assign hasUnique = false>
<#list propertyList as prop>
<#assign isPropId = prop.equals(pojo.identifierProperty)>
<#if !isPropId || prop.value.identifierGeneratorStrategy == "assigned">
<#if isUnique(prop)>
<#assign hasUnique = true>
</#if>
</#if>
</#list>
<#if hasUnique || relationList?size gt 0>
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;

import java.util.List;
import java.util.ArrayList;
</#if>
<#if hasUnique>

import net.sourceforge.stripes.validation.ValidationMethod;
import net.sourceforge.stripes.validation.ValidationErrors;
import net.sourceforge.stripes.validation.LocalizableError;
</#if>

/**
 * Class which handles save/update/delete for ${entityName}
 * created: ${date?string("dd.MM.yyyy HH:mm:ss")}
 */
<#assign idName = pojo.identifierProperty.name>
<#assign idTypeName = pojo.identifierProperty.type.returnedClass.name>
public class ${entityName}Edit implements ActionBean {

<#--
=======================================================================================================================
 PROPERTY DECLARATION
=======================================================================================================================
 -->
  private ActionBeanContext context;
<#if pojo.isComponent(pojo.identifierProperty)>
  private ${entityName} ${componentName};
<#else>
  private ${entityName} ${componentName} = new ${entityName}();
</#if>

<#--
=======================================================================================================================
 CONSTRUCTOR DECLARATION
=======================================================================================================================
 -->
  /**
   * Constructor, initialization of instance
   */
  public ${entityName}Edit() {
    super();
<#if pojo.isComponent(pojo.identifierProperty)>

    // Creates search instanstance
    ${componentName} = new ${entityName}();
    ${componentName}.setId(new ${entityName}Id());
</#if>
  }

<#--
=======================================================================================================================
 ENTITY INSTANCE SETTER/GETTER
=======================================================================================================================
 -->
  /**
   * Sets entity instance
   * @param ${componentName} instance
   */
  public void set${entityName}(${entityName} ${componentName}) {
    this.${componentName} = ${componentName};
  }

  /**
   * Returns entity instance (used for filters)
   * @return ${entityName} instance
   */
  @ValidateNestedProperties({
<#-- Calculate number of validation parameters  -->
<#assign valParamCount = 0>
<#foreach prop in propertyList>
<#assign isPropId = prop.equals(pojo.identifierProperty)>
<#if !isPropId || prop.value.identifierGeneratorStrategy == "assigned">
<#if pojo.isComponent(prop)>
<#foreach cprop in prop.value.propertyIterator>
<#assign column = cprop.columnIterator.next()>
<#if (!column.nullable && !isBoolean(cprop)) || isString(cprop)>
<#assign valParamCount = valParamCount + 1>
</#if>
</#foreach>
<#else>
<#assign column = prop.columnIterator.next()>
<#if (!column.nullable && !isBoolean(prop)) || isString(prop)>
<#assign valParamCount = valParamCount + 1>
</#if>
</#if>
</#if>
</#foreach>
<#-- Validation parameters  -->
<#assign tmpIndex = 0>
<#list propertyList as prop>
<#assign isPropId = prop.equals(pojo.identifierProperty)>
<#if !isPropId || prop.value.identifierGeneratorStrategy == "assigned">
<#if pojo.isComponent(prop)>
<#list prop.value.propertyIterator as cprop>
<#if !isNullable(cprop) && !isBoolean(cprop)>
<#if isString(cprop)>
<#assign tmpIndex = tmpIndex + 1>
    @Validate(field="${prop.name}.${cprop.name}", required=true, maxlength=${lengthToStr(cprop)})<#if tmpIndex < valParamCount>,</#if>
<#else>
<#assign tmpIndex = tmpIndex + 1>
    @Validate(field="${prop.name}.${cprop.name}", required=true)<#if tmpIndex < valParamCount>,</#if>
</#if>
<#elseif isString(cprop)>
<#assign tmpIndex = tmpIndex + 1>
    @Validate(field="${prop.name}.${cprop.name}", maxlength=${lengthToStr(cprop)})<#if tmpIndex < valParamCount>,</#if>
</#if>
</#list>
<#else>
<#if !isNullable(prop) && !isBoolean(prop)>
<#if isString(prop)>
<#assign tmpIndex = tmpIndex + 1>
    @Validate(on="doSave", field="${prop.name}", required=true, maxlength=${lengthToStr(prop)})<#if tmpIndex < valParamCount>,</#if>
<#else>
<#assign tmpIndex = tmpIndex + 1>
    @Validate(on="doSave", field="${prop.name}", required=true)<#if tmpIndex < valParamCount>,</#if>
</#if>
<#elseif isString(prop)>
<#assign tmpIndex = tmpIndex + 1>
    @Validate(on="doSave", field="${prop.name}", maxlength=${lengthToStr(prop)})<#if tmpIndex < valParamCount>,</#if>
</#if>
</#if>
</#if>
</#list>
  })
  public ${entityName} get${entityName}() {
    return ${componentName};
  }

<#--
=======================================================================================================================
 PROPERTIES VALIDATION
=======================================================================================================================
 -->
<#-- List all properties, create validation for unique properties -->
<#assign propIdName = pojo.identifierProperty.name>
<#list propertyList as prop>
<#assign isPropId = prop.equals(pojo.identifierProperty)>
<#if !isPropId || prop.value.identifierGeneratorStrategy == "assigned">
<#if isUnique(prop)>
  /**
   * Applies uniquecity validation
   */
  @ValidationMethod(on="doSave")
  public void validate${prop.name?cap_first}Unique() {

    // Create criteria for uniquecity test
    List<Criterion> crits = new ArrayList<Criterion>();
    crits.add(Restrictions.eq("${prop.name}", ${componentName}.get${prop.name?cap_first}()));
    if (${componentName}.get${propIdName?cap_first}() != null) {
      crits.add(Restrictions.ne("${propIdName}", ${componentName}.get${propIdName?cap_first}()));
    }

    // Find how many rows in actual table match the example
    long count = new ${entityName}DAO().findCountByCriteria((Criterion[]) crits.toArray(new Criterion[crits.size()]));

    // If there are matches, create validation error
    if (count > 0) {
      ValidationErrors errors = getContext().getValidationErrors();
      errors.add("${prop.name}", new LocalizableError("validation.unique.valueAlreadyPresent"));
      getContext().setValidationErrors(errors);
    }
  }
</#if>
</#if>
</#list>

<#--
=======================================================================================================================
 FOREIGN KEYS SETTERS/GETTERS
=======================================================================================================================
 -->
<#-- List all relation properties, create setters and getters for foreign keys -->
<#list relationList as prop>
<#assign shortName = prop.type.name?split(".")?last/>
<#assign referencedTypeId = findEntity(shortName).identifierProperty/>
<#assign pickerName = getPickerName(shortName) />
  /**
   * Sets foreign key for ${prop.name}
   * @param ${referencedTypeId.name} key for referenced object
   */
  public void set${prop.name?cap_first}Key(${referencedTypeId.type.name?split(".")?last?cap_first} ${referencedTypeId.name}) {
    ${shortName}DAO ${shortName?uncap_first}DAO = new ${shortName}DAO();
    ${shortName} ${prop.name} = ${shortName?uncap_first}DAO.findById(${referencedTypeId.name}, false);
    ${componentName}.set${prop.name?cap_first}(${prop.name});
  }

  /**
   * Returns foreign key for ${prop.name}
   * @return key for referenced object
   */
  public ${referencedTypeId.type.name?split(".")?last?cap_first} get${prop.name?cap_first}Key() {
    ${shortName} ${prop.name} = ${componentName}.get${prop.name?cap_first}();
    return ${prop.name} == null ? null : ${prop.name}.get${referencedTypeId.name?cap_first}();
  }

  /**
   * Returns "entity picker display name" for ${prop.name}
   * @return picker display name
   */
  public String get${prop.name?cap_first}PickerDisplayName() {
<#if pickerName?starts_with("View") && pickerName?ends_with("Picker")>

    // Get selected ID
    ${referencedTypeId.type.name?split(".")?last?cap_first} key = get${prop.name?cap_first}Key();
    if (key == null) {
      return "";
    }

    // Find picker object with given ID and return its "picker name"
    List<Criterion> crits = new ArrayList<Criterion>();
    crits.add(Restrictions.eq("id.${referencedTypeId.name}", key));
    ${pickerName}DAO tmpDAO = new ${pickerName}DAO();
    List<${pickerName}> list = tmpDAO.findByCriteria((Criterion[]) crits.toArray(new Criterion[crits.size()]));
    return list.size() > 0 ? list.get(0).getId().getPickerDisplay() : "";
<#else>
    return "";
</#if>
  }
</#list>

<#--
=======================================================================================================================
 EDITATATION METHODS (ACTION MANAGEMENT)
=======================================================================================================================
 -->
  /**
   * Sets context
   * @param context action bean context
   */
  public void setContext(ActionBeanContext context) {
    this.context = context;
  }

  /**
   * Returns context
   * @return context
   */
  public ActionBeanContext getContext() {
    return this.context;
  }

  /**
   * Loads entity for editation
   * @return resolution
   * @throws java.io.IOException exception
   */
  public Resolution doLoad() throws Exception {

    // Loads ${componentName} for editation
    if (${componentName} != null && ${componentName}.get${pojo.identifierProperty.name?cap_first}() != null) {
      Session session = SessionFactoryManager.getFactory().openSession();
      Transaction tx = session.beginTransaction();
      try {
        ${componentName} = (${entityName}) session.load(${entityName}.class, ${componentName}.get${pojo.identifierProperty.name?cap_first}());
        tx.commit();
      } catch (Exception ex) {
        tx.rollback();
        throw ex;
      } finally {
        //session.close();
      }
    }

    // Redirect to list
    return new ForwardResolution("/${entityName}Edit.jsp");
  }

  /**
   * Saves entity
   * @return resolution
   * @throws java.io.IOException exception
   */
  @DefaultHandler
  public Resolution doSave() throws java.io.IOException {

    // Save entity
    new ${entityName}DAO().makePersistent(${componentName});

    // Redirect to list
    return new RedirectResolution("/${entityName}List.jsp");
  }

  /**
   * Deletes entity
   * @return resolution
   * @throws java.io.IOException exception
   */
  public Resolution doDelete() throws java.io.IOException {

    // Delete entity
    new ${entityName}DAO().makeTransient(${componentName});

    // Redirect to list
    return new RedirectResolution("/${entityName}List.jsp");
  }
}
